package com.phantasy
{
	import flash.utils.ByteArray;
	import flash.utils.Endian;
	import flash.utils.getDefinitionByName;

	public dynamic class Message
	{
		public function Message()
		{
			
		}
		/**
		 *编码 
		 * @param message
		 * @return 
		 * 
		 */		
		public static function encode(message:Message):ByteArray
		{
			var data:ByteArray = new ByteArray();
			data.endian = Endian.BIG_ENDIAN;
			data.writeByte(131);
			pack(message, data);
			return data;
		}
		/**
		 *解码 
		 * @param data
		 * 
		 */		
		public function decode(data:ByteArray):void
		{
			data.readByte();
			var arr:Array = new Array();
			arr = this.decodeErlangTerm(data);
			this.unpack(arr);
		}
		
		/**
		 *打包数据 
		 * @param ms		消息体
		 * @param data		131数据
		 * @return 			打包后的数据
		 * 
		 */		
		public static function pack(_arg1:Message, _arg2:ByteArray):ByteArray
		{
			var _local8:String;
			var _local10:ByteArray;
			var _local11:Number;
			var _local12:int;
			var _local13:String;
			var _local14:ByteArray;
			var _local15:Number;
			var _local16:int;
			var _local17:ByteArray;
			if (_arg1 == null)
			{
				_arg2.writeByte(100);
				_arg2.writeUTF("undefined");
				return (_arg2);
			}
			var _local3:Array = _arg1.getAttributes();
			var _local4:int = _local3.length;
			var _local5:int;
			var _local6:int;
			var _local7:int;
			if (_local4 > 0xFF)
			{
				_arg2.writeByte(105);
				_arg2.writeInt((_local4 + 1));
			}
			else
			{
				_arg2.writeByte(104);
				_arg2.writeByte((_local4 + 1));
			}
			_arg2.writeByte(100);
			var _local9:String = _arg1.getClassName();
			_arg2.writeUTF(_local9);
			_local6 = 0;
			while (_local6 < _local4)
			{
				_local8 = _local3[_local6][1].toString().toLowerCase();
				if (_local8 == "int")
				{
					_arg2.writeByte(98);
					_arg2.writeInt(_arg1[_local3[_local6][0]]);
				}
				else
				{
					if ((((_local8 == "double")) || ((_local8 == "number"))))
					{
						if ((((_arg1[_local3[_local6][0]] < 2147483647)) && ((_arg1[_local3[_local6][0]] > -2147483647))))
						{
							_arg2.writeByte(98);
							_arg2.writeInt(_arg1[_local3[_local6][0]]);
						}
						else
						{
							_arg2.writeByte(110);
							_local10 = new ByteArray();
							_local11 = _arg1[_local3[_local6][0]];
							while (_local11 > 1)
							{
								_local10.writeByte(int((_local11 & 0xFF)));
								_local11 = (_local11 / 0x0100);
							};
							_arg2.writeByte(_local10.length);
							if (_arg1[_local3[_local6][0]] > 0)
							{
								_arg2.writeByte(0);
							}
							else
							{
								_arg2.writeByte(1);
							};
							_local12 = 0;
							while (_local12 <= (_local10.length - 1))
							{
								_arg2.writeByte(_local10[_local12]);
								_local12++;
							}
						}
					}
					else
					{
						if (_local8 == "string")
						{
							_arg2.writeByte(107);
							_arg2.writeUTF(_arg1[_local3[_local6][0]]);
						}
						else
						{
							if ((((_local8 == "bool")) || ((_local8 == "boolean"))))
							{
								_arg2.writeByte(100);
								if (_arg1[_local3[_local6][0]])
								{
									_arg2.writeUTF("true");
								}
								else
								{
									_arg2.writeUTF("false");
								}
							}
							else
							{
								if (_local8 == "array")
								{
									_local5 = (_arg1[_local3[_local6][0]] as Array).length;
									if (_local5 > 0)
									{
										_arg2.writeByte(108);
										_arg2.writeUnsignedInt(_local5);
										_local13 = _local3[_local6][2].toString().toLowerCase();
										_local7 = 0;
										while (_local7 < _local5)
										{
											if (_local13 == "int")
											{
												_arg2.writeByte(98);
												_arg2.writeInt(_arg1[_local3[_local6][0]][_local7]);
											}
											else
											{
												if ((((_local13 == "double")) || ((_local13 == "number"))))
												{
													if ((((_arg1[_local3[_local6][0]][_local7] < 2147483647)) && ((_arg1[_local3[_local6][0]][_local7] > -2147483647))))
													{
														_arg2.writeByte(98);
														_arg2.writeInt(_arg1[_local3[_local6][0]][_local7]);
													}
													else
													{
														_arg2.writeByte(110);
														_local14 = new ByteArray();
														_local15 = _arg1[_local3[_local6][0]][_local7];
														while (_local15 > 1)
														{
															_local14.writeByte(int((_local15 & 0xFF)));
															_local15 = (_local15 / 0x0100);
														}
														_arg2.writeByte(_local14.length);
														if (_arg1[_local3[_local6][0]][_local7] > 0)
														{
															_arg2.writeByte(0);
														}
														else
														{
															_arg2.writeByte(1);
														}
														_local16 = 0;
														while (_local16 <= (_local14.length - 1))
														{
															_arg2.writeByte(_local14[_local16]);
															_local16++;
														}
													}
												}
												else
												{
													if (_local13 == "string")
													{
														_arg2.writeByte(107);
														_arg2.writeUTF(_arg1[_local3[_local6][0]][_local7]);
													}
													else
													{
														if ((((_local13 == "bool")) || ((_local13 == "boolean"))))
														{
															_arg2.writeByte(100);
															if (_arg1[_local3[_local6][0]][_local7])
															{
																_arg2.writeUTF("true");
															}
															else
															{
																_arg2.writeUTF("false");
															}
														}
														else
														{
															pack(_arg1[_local3[_local6][0]][_local7], _arg2);
														}
													}
												}
											}
											_local7++;
										}
									}
									_arg2.writeByte(106);
								}
								else
								{
									if (_local8 == "bytes")
									{
										_arg2.writeByte(109);
										_local17 = (_arg1[_local3[_local6][0]] as ByteArray);
										_arg2.writeInt(_local17.length);
										_arg2.writeBytes(_local17, _arg2.position, _local17.length);
									}
									else
									{
										pack(_arg1[_local3[_local6][0]], _arg2);
									}
								}
							}
						}
					}
				}
				_local6++;
			}
			return _arg2;
		}
		
		public function unpack(_arg1:Array):Message
		{
			var _local6:Message;
			var _local7:Class;
			var _local8:String;
			var _local9:ByteArray;
			var _local10:ByteArray;
			var _local11:int;
			var _local12:int;
			var _local13:Array;
			var _local14:String;
			var _local15:ByteArray;
			var _local16:int;
			var _local17:int;
			var _local2:String = this.getClassName();
			if (_arg1[0] == _local2)
			{
				_local6 = this;
			}
			else
			{
				_local7 = getDefinitionByName("com.phantasy.proto." + _arg1[0]) as Class;
				_local6 = new (_local7)();
			}
			var _local3:int;
			var _local4:Array = _local6.getAttributes();
			var _local5:int = 1;
			while (_local5 < _arg1.length)
			{
				_local8 = _local4[(_local5 - 1)][1].toString().toLowerCase();
				if (_local8 == "int")
				{
					_local6[_local4[(_local5 - 1)][0]] = int(_arg1[_local5]);
				}
				else
				{
					if (_local8 == "bytes")
					{
						_local9 = new ByteArray();
						_local9.writeUTFBytes(_local4[(_local5 - 1)][1]);
						_local6[_local4[(_local5 - 1)][0]] = _local15;
					}
					else
					{
						if ((((_local8 == "double")) || ((_local8 == "number"))))
						{
							_local6[_local4[(_local5 - 1)][0]] = Number(_arg1[_local5]);
						}
						else
						{
							if (_local8 == "string")
							{
								if (_arg1[_local5] == "undefined")
								{
									_local6[_local4[(_local5 - 1)][0]] = null;
								}
								else
								{
									_local10 = new ByteArray();
									if ((_arg1[_local5] as Array) != null)
									{
										_local11 = (_arg1[_local5] as Array).length;
										_local12 = 0;
										while (_local12 < _local11)
										{
											_local10.writeByte(_arg1[_local5][_local12]);
											_local12++;
										};
										_local10.position = 0;
										_local6[_local4[(_local5 - 1)][0]] = _local10.readUTFBytes(_local11);
									}
									else
									{
										_local6[_local4[(_local5 - 1)][0]] = _arg1[_local5].toString();
									};
								};
							}
							else
							{
								if ((((_local8 == "bool")) || ((_local8 == "boolean"))))
								{
									if (_arg1[_local5] != "undefined")
									{
										_local6[_local4[(_local5 - 1)][0]] = (((_arg1[_local5])=="true") ? true : false);
									};
								}
								else
								{
									if (_local8 == "array")
									{
										_local13 = new Array();
										if (_arg1[_local5] != "undefined")
										{
											_local14 = _local4[(_local5 - 1)][2].toString().toLowerCase();
											if (_local14 == "int")
											{
												if (_arg1[_local5] != "undefined")
												{
													_local3 = 0;
													while (_local3 < _arg1[_local5].length)
													{
														_local13.push(int(_arg1[_local5][_local3]));
														_local3++;
													};
												};
											}
											else
											{
												if ((((_local14 == "double")) || ((_local14 == "number"))))
												{
													_local3 = 0;
													while (_local3 < _arg1[_local5].length)
													{
														_local13.push(Number(_arg1[_local5][_local3]));
														_local3++;
													};
												}
												else
												{
													if (_local14 == "string")
													{
														_local3 = 0;
														while (_local3 < _arg1[_local5].length)
														{
															if (_arg1[_local5] == "undefined")
															{
																_local13.push(null);
															}
															else
															{
																_local15 = new ByteArray();
																if ((_arg1[_local5][_local3] as Array) != null)
																{
																	_local16 = (_arg1[_local5][_local3] as Array).length;
																	_local17 = 0;
																	while (_local17 < _local16)
																	{
																		_local15.writeByte(_arg1[_local5][_local3][_local17]);
																		_local17++;
																	};
																	_local15.position = 0;
																	_local13.push(_local15.readUTFBytes(_local16));
																}
																else
																{
																	_local13.push(_arg1[_local5][_local3].toString());
																};
															};
															_local3++;
														};
													}
													else
													{
														if ((((_local14 == "bool")) || ((_local14 == "boolean"))))
														{
															_local3 = 0;
															while (_local3 < _arg1[_local5].length)
															{
																_local13.push((((_arg1[_local5][_local3])=="true") ? true : false));
																_local3++;
															};
														}
														else
														{
															if (_arg1[_local5] != "undefined")
															{
																_local3 = 0;
																while (_local3 < _arg1[_local5].length)
																{
																	_arg1[_local5][_local3][0] = _local4[(_local5 - 1)][2];
																	_local13.push(this.unpack(_arg1[_local5][_local3]));
																	_local3++;
																};
															};
														};
													};
												};
											};
										};
										_local6[_local4[(_local5 - 1)][0]] = _local13;
									}
									else
									{
										if (_arg1[_local5] == "undefined")
										{
											_local6[_local4[(_local5 - 1)][0]] = null;
										}
										else
										{
											_arg1[_local5][0] = _local4[(_local5 - 1)][1];
											_local6[_local4[(_local5 - 1)][0]] = this.unpack(_arg1[_local5]);
										}
									}
								}
							}
						}
					}
				}
				_local5++;
			}
			return (_local6);
		}
		
		
		protected function decodeErlangTerm(_arg1:ByteArray):*
		{
			var _local3:int;
			var _local4:int;
			var _local5:ByteArray;
			var _local6:ByteArray;
			var _local7:int;
			var _local8:Array;
			var _local9:Array;
			var _local10:Array;
			var _local11:Array;
			var _local12:int;
			var _local13:Number;
			var _local14:int;
			var _local15:int;
			var _local16:Number;
			var _local17:int;
			var _local2:int = _arg1.readUnsignedByte();
			switch (_local2)
			{
				case 97:
					return (_arg1.readUnsignedByte());
				case 98:
					return (_arg1.readInt());
				case 99:
					_local5 = new ByteArray();
					_arg1.readBytes(_local5, 0, 31);
					return (Number(_local5.toString()));
				case 115:
					_local4 = _arg1.readUnsignedByte();
					_local6 = new ByteArray();
					_local6.readBytes(_arg1, _arg1.position, _local4);
					return (_local6.toString());
				case 109:
					_local7 = _arg1.readUnsignedInt();
					return (_arg1.readUTFBytes(_local7));
				case 107:
					_local4 = _arg1.readUnsignedShort();
					_local8 = new Array();
					_local3 = 0;
					while (_local3 < _local4)
					{
						_local8.push(_arg1.readUnsignedByte());
						_local3++;
					}
					return (_local8);
				case 108:
					_local4 = _arg1.readUnsignedInt();
					_local9 = new Array();
					_local3 = 0;
					while (_local3 < _local4)
					{
						_local9.push(this.decodeErlangTerm(_arg1));
						_local3++;
					}
					_arg1.readByte();
					return (_local9);
				case 106:
					return (new Array());
				case 104:
					_local4 = _arg1.readUnsignedByte();
					_local10 = new Array();
					_local3 = 0;
					while (_local3 < _local4)
					{
						_local10.push(this.decodeErlangTerm(_arg1));
						_local3++;
					}
					return (_local10);
				case 105:
					_local4 = _arg1.readUnsignedInt();
					_local11 = new Array();
					_local3 = 0;
					while (_local3 < _local4)
					{
						_local11.push(this.decodeErlangTerm(_arg1));
						_local3++;
					}
					return (_local11);
				case 100:
					return (_arg1.readUTF());
				case 110:
					_local4 = _arg1.readUnsignedByte();
					_local12 = _arg1.readUnsignedByte();
					_local13 = 0;
					_local14 = 0;
					_local3 = 0;
					while (_local3 < _local4)
					{
						_local14 = _arg1.readUnsignedByte();
						_local13 = (_local13 + (_local14 * Math.pow(0x0100, _local3)));
						_local3++;
					};
					if (_local12 == 1)
					{
						_local13 = -(_local13);
					}
					return (_local13);
				case 111:
					_local4 = _arg1.readUnsignedByte();
					_local15 = _arg1.readUnsignedByte();
					_local16 = 0;
					_local17 = 0;
					_local3 = 0;
					while (_local3 < _local4)
					{
						_local17 = _arg1.readUnsignedByte();
						_local16 = (_local16 + (_local17 * Math.pow(0x0100, _local3)));
						_local3++;
					};
					if (_local15 == 1)
					{
						_local16 = -(_local16);
					}
					return (_local16);
				default:
					throw (new Error("未知类型:", _local2));
			}
		}
		
		
		/**
		 *获取方法名 
		 * @return 
		 * 
		 */		
		public function getMethodName():String
		{
			return null;
		}
		/**
		 *获取类名 
		 * @return 
		 * 
		 */		
		public function getClassName():String
		{
			return null;
		}
		/**
		 *获取属性 
		 * @return 
		 * 
		 */		
		public function getAttributes():Array
		{
			return null;
		}
	}
}